﻿#include "net.h"
#include "AvType.h"
#include "log.h"

int NetSockPair(int* in, int* out) {
	return 0;
}

static int sock_connect_select(int sock, struct sockaddr_in* AddrIn, int timeo)
{
	int ret = 0;
	fd_set wset;
	struct timeval tval;
	ret = connect(sock, (struct sockaddr*)AddrIn, sizeof(struct sockaddr));
	if (ret == 0) {
		return 0;
	}
	FD_ZERO(&wset);
	FD_SET(sock, &wset);
	tval.tv_sec = timeo / 1000;
	tval.tv_usec = timeo % 1000;
	ret = select(sock + 1, NULL, &wset, NULL, &tval);
	if (ret == 0) {
		_logDebugWarn("Connect select Time out [%d]ms  remote [%s][%d]\n", timeo, inet_ntoa(AddrIn->sin_addr), ntohs(AddrIn->sin_port));
		return -1;
	}
	else if (FD_ISSET(sock, &wset)) {
		int error_code = 0;
		socklen_t len = sizeof(error_code);
		ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&error_code, &len);
		if (ret < 0 || error_code != 0) {
			_logDebugWarn("Connect getsockopt error_code[%d] remote [%s][%d]\n", error_code, inet_ntoa(AddrIn->sin_addr), ntohs(AddrIn->sin_port));
			return -1;
		}
	}
	else {
		_logDebugErr("Connect select remote [%s][%d]\n", inet_ntoa(AddrIn->sin_addr), ntohs(AddrIn->sin_port));
		return -1;
	}
	return 0;
}


int NetGetIpAddrByHost(const char* Host, char IpAddr[][32], int* Size)
{
	struct addrinfo* res, * pt;
	struct sockaddr_in* sinp;
	const char* addr;
	int succ = 0, i = 0;
	char abuf[INET_ADDRSTRLEN];
	int bRepetition = -1;
#ifdef 	__HuaweiLite__
	succ = netliteos_getaddrinfo(Host, NULL, NULL, &res);
#else
	succ = getaddrinfo(Host, NULL, NULL, &res);
#endif	
	if (succ != 0) {
		_logDebugErr("Can't get address info! error code = %d", succ);
		return -1;
	}
	int j = 0;
	for (pt = res, i = 0; pt != NULL && i < *Size; pt = pt->ai_next) {
		sinp = (struct sockaddr_in*)pt->ai_addr;
		addr = (const char*)inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
		bRepetition = -1;

		for (j = 0; j < i; j++) {
			if (0 == strcmp(IpAddr[j], addr)) {
				bRepetition = 0;
				break;
			}
		}
		if (bRepetition == -1) {
			sprintf(IpAddr[i], "%s", addr);
			i++;
		}
	}
	freeaddrinfo(res);
	*Size = i;
	return 0;
}
int NetConnect(char* Addr, int Port, int timeoMs)
{
	int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock <= 0) {
		return -1;
	}
#if defined(WIN32)
	DWORD yes = 1;
	if (ioctlsocket(sock, FIONBIO, &yes) == SOCKET_ERROR) {
		return WSAGetLastError();
	}
#else	
	int yes = 1;
	if (ioctl(sock, FIONBIO, &yes) != 0) {
		return errno;
	}
	size_t size = 4096;
	setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&size, sizeof(unsigned int));
#endif 

	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(Addr);
	addr.sin_port = htons(Port);


	int ret = sock_connect_select(sock, &addr, timeoMs);
	if (ret != 0) {
		NetClose(sock);
		sock = -1;
	}
	return sock;
}

void NetClose(int sock) {
#if defined(WIN32)
	closesocket(sock);
#else
	close(sock);
#endif
}
